ByteCodeMethod
). Unlike function definitions using the function
construct, anonymous function definitions don't cause a variable to be declared implicitly, and so are not accessible by naming the variable to which they are bound (hence the term anonymous function). Anonymous functions are useful for nesting function definitions in other expressions, or as arguments to other functions.( [ positionalArgs ] [ RestArg ] [ KeywordArgs ] -> body )Anonymous functions can be defined with the same three types of arguments as regular functions: positional arguments, rest arguments, and keyword arguments. Just as with regular functions, all three types of arguments are optional, but must be specified in the order shown.
(n -> n * n)
(a b -> a + b)
(#rest nums -> for i in nums do print (i * 10))
Anonymous functions can be used wherever normal function calls are used:
function addTwo a b -> a + b
addTwo 4 5
9
(a b -> a + b) 4 5
9
for i in #(1,2,3,4) collect (n -> n as String) i
#("1", "2", "3", "4")
In the ScriptX core classes, many generic functions take a function as an argument. An anonymous function is an ideal way to pass a function object as an argument, since it doesn't require assigning a name. The following example demonstrates the use of an anonymous function in a callback script. The second argument in the third expression, addTimeCallback
, registers a callback that will print the clock's time in 15 seconds. This printing action is called as an anonymous function.
global myClock := new ClockBecause an anonymous function expression evaluates to a function object, you can assign an anonymous function expression to a variable, and then use that variable name to call the function, just as if you had created that function with the
myClock.rate := 1
addTimeCallback myClock (c -> print c.time) \
myClock #() (myClock.time + 15) true
function
expression. The difference is that the variable to which you assign the anonymous function is not a constant variable, so it can be reassigned to any other object.cubeMe := (a -> a * a * a)
cubeMe 2
8
As mentioned earlier, if your function requires recursion (a recursive function calls itself to accomplish an operation), you cannot use an anonymous function. Recursion depends on a special binding of a variable name to a function definition before that function object has been created. The function
expression provides a local binding that allows recursion. An anonymous function does not.
-- this is OK
function sumTheNum arg -> (
if arg <= 0 then return 0
else return (arg + (sumTheNum (arg - 1)))
)
sumTheNum 2
3
sumTheNum 10
55
In the following example, an anonymous function is bound to a variable. It works as intended at runtime. However, it is less efficient than the same function would be with a function
binding, since the compiler cannot optimize for recursion.
-- an inefficient way to do recursion
sumTheNum2 := (arg -> (
if arg = 0 then return 0
else return (arg + (sumTheNum2 (arg - 1)))
))
The body of an anonymous function can be a series of expressions. The following script repeats an example that first appeared on page 90, where it was defined using a named function.
global backwards := new String string:""
global palindrome := "Satan, oscillate my metallic sonatas"
for i in palindrome collect into backwards by \
(sequence value -> prepend sequence value; sequence) i
"satanos cillatem ym etallicso ,nataS"
In this example, the body of the anonymous function contains two expressions. At each iteration through palindrome, the anonymous function prepends i to backwards and then returns the new version of backwards. The value of the final expression (the final version of backwards in this example) is the return value of the entire function. A ScriptX for
expression can act as a collector, accumulating items into a collection. Since the by
clause in a for
expression must evaluate to a function that returns the collection itself, this anonymous function combines prepend
and an expression that returns the collection. In this way, the anonymous function makes it possible to use prepend
as a collector function. For information on the for
expression, see the discussion which begins on page 84.
This document is part of the ScriptX Language Guide, one of the volumes of the ScriptX Technical Reference Series. ScriptX is developed by the ScriptX Engineering Team at Apple Computer, successor to the Kaleida Engineering Team at Kaleida Labs, Inc.